package com.mxsoft.takeaway.trace;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Slf4j
@Component
@Aspect
public class MTrace {
    @Around("execution(* com.mxsoft.takeaway..*(..))")
    public Object logMethod(ProceedingJoinPoint joinPoint) throws Throwable {

        Object retVal = joinPoint.proceed();
        ObjectMapper objectMapper = new ObjectMapper();
        // 如果为空则不输出
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
        // 对于空的对象转json的时候不抛出错误
        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        // 禁用序列化日期为timestamps
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        // 禁用遇到未知属性抛出异常
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        // 视空字符传为null
        objectMapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);

        // 低层级配置
        objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
        // 允许属性名称没有引号
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        // 允许单引号
        objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        // 取消对非ASCII字符的转码
        objectMapper.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, false);
        try {
            long id = Thread.currentThread().getId();
            StringBuilder logInfo = new StringBuilder();
            logInfo.append("Thread -> " + id);
            logInfo.append(" class -> ");
            logInfo.append(joinPoint.getTarget().getClass().getName());
            logInfo.append(".");
            logInfo.append(joinPoint.getSignature().getName());
            logInfo.append("(");

            Object[] args = joinPoint.getArgs();
            for (int i = 0; i < args.length; i++) {
                if (args[i] instanceof HttpServletRequest || args[i] instanceof HttpServletResponse) {
                    continue;
                }
                logInfo.append(objectMapper.writeValueAsString(args[i])).append(",");
            }
            if (args.length > 0) {
                logInfo.deleteCharAt(logInfo.length() - 1);
            }

            logInfo.append(")");
            logInfo.append(" retVal: ");
            logInfo.append(objectMapper.writeValueAsString(retVal));
            log.info(logInfo.toString());
        } catch (Exception e) {
            log.error("log error, Exception: ", e);
        }
        return retVal;
    }
}
